package com.jeeplus.mob.payUtile;

import java.io.File;
import java.io.FileInputStream;
import java.security.KeyStore;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;

import javax.net.ssl.SSLContext;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContexts;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


public class PayUtil {
	private static Logger log = LoggerFactory.getLogger(PayUtil.class);

	// 支付场景一，统一下单支付接口 微信公众JSAPI
	public static Map<String, String> wxPays(String body, String totalFee, String orderNo, HttpServletRequest reques,
			String openId) throws Exception {
		Map<String, String> resultMap = new HashMap();
		double orderMoney = Double.valueOf(totalFee) * 100;
		String st = String.valueOf(orderMoney);
		st = st.substring(0, st.indexOf("."));
		OurWxPayConfig ourWxPayConfig = new OurWxPayConfig();
		WXPay wxPay = new WXPay(ourWxPayConfig);
		Map<String, String> data = new HashMap();
		data.put("appid", WeChatConfig.APP_ID);
		data.put("mch_id", WeChatConfig.MCH_ID);
		data.put("nonce_str", WXPayUtil.generateNonceStr());
		data.put("body", body);
		data.put("out_trade_no", orderNo);
		data.put("total_fee", st);
		data.put("spbill_create_ip", WXPayUtil.getIpAddr(reques));
		data.put("notify_url", WeChatConfig.NOTIFY_URL);
		data.put("trade_type", "JSAPI");
		data.put("openid", openId);
		String s = WXPayUtil.generateSignature(data, WeChatConfig.APP_KEY);
		data.put("sign", s);
		Map<String, String> respData = wxPay.unifiedOrder(data);
		if (((String) respData.get("return_code")).equals("SUCCESS")) {
			Map<String, String> repData = new HashMap();
			repData.put("appId", WeChatConfig.APP_ID);
			repData.put("timeStamp", String.valueOf(System.currentTimeMillis() / 1000L));
			repData.put("nonceStr", WXPayUtil.generateNonceStr());
			repData.put("package", "prepay_id=" + respData.get("prepay_id"));
			repData.put("signType", "MD5");
			String sign = WXPayUtil.generateSignature(repData, WeChatConfig.APP_KEY);
			repData.put("paySign", sign);
			repData.put("prepay_id", respData.get("prepay_id"));
			return repData;
		} else {
			return respData;
		}
	}

	// WX扫码支付场景二，统一下单支付接口
	public static String wxPay(String body, String totalFee, String orderNo, String attach) throws Exception {
		// 把请求参数打包成数组
		double orderMoney = Double.valueOf(totalFee) * 100;
		String st = String.valueOf(orderMoney);
		st = st.substring(0, st.indexOf("."));
		OurWxPayConfig ourWxPayConfig = new OurWxPayConfig();
		WXPay wxPay = new WXPay(ourWxPayConfig);
		Map<String, String> params = new TreeMap<String, String>();
		params.put("appid", WeChatConfig.APP_ID);
		params.put("mch_id", WeChatConfig.MCH_ID);
		params.put("nonce_str", WXPayUtil.generateNonceStr());
		params.put("sign_type", WXPayConstants.MD5);
		params.put("device_info", "WEB");
		params.put("notify_url", WeChatConfig.NOTIFY_URL);
		params.put("trade_type", "NATIVE");
		params.put("out_trade_no", orderNo);
		params.put("body", body);
		params.put("total_fee", st);
//		params.put("attach", attach);
		params.put("spbill_create_ip", "127.0.0.1");
		params.put("sign", WXPayUtil.generateSignature(params, WeChatConfig.APP_KEY));
		Map<String, String> resultMap = wxPay.unifiedOrder(params);
		// 验证结果是否成功，如果成功则返回相对应的二维码链接地址。否则
		if (WXPayConstants.SUCCESS.equals(resultMap.get("result_code"))) {
			log.info(resultMap.get("code_url"));
			return resultMap.get("code_url");
		} else {
			log.info(resultMap.get("code_url"));
			throw new Exception(resultMap.get("err_code_des"));
		}
	}

	/**
	 * 微信申请退款
	 * 
	 * @param totalFee    订单金额
	 * @param orderNo     商户订单号
	 * @param outRefundNo 商户退款单号，注：同一退款单号多次请求只退一笔。
	 *                    微信支付退款支持单笔交易分多次退款，多次退款需要提交原支付订单的商户订单号和设置不同的退款单号。
	 *                    申请退款总金额不能超过订单金额。 一笔退款失败后重新提交，请不要更换退款单号，请使用原商户退款单号
	 * @return
	 * @throws Exception
	 */
	public static Map<String, String> wxRefund(String totalFee, String TRANSACTION_ID, String orderNo,
			String outRefundNo) throws Exception {
		String url = WXPayConstants.REFUND_URL;
		OurWxPayConfig ourWxPayConfig = new OurWxPayConfig();
		WXPay wxPay = new WXPay(ourWxPayConfig);
		Map<String, String> data = new HashMap();
		double orderMoney = Double.valueOf(totalFee) * 100;
		String st = String.valueOf(orderMoney);
		st = st.substring(0, st.indexOf("."));
		data.put("transaction_id", TRANSACTION_ID);
		data.put("total_fee", st);
		data.put("refund_fee", st);
		data.put("appid", WeChatConfig.APP_ID);
		data.put("mch_id", WeChatConfig.MCH_ID);
		data.put("nonce_str", WXPayUtil.generateNonceStr());
		data.put("out_refund_no", outRefundNo);// 退款单号
		data.put("notify_url", "");
		String s = WXPayUtil.generateSignature(data, WeChatConfig.APP_KEY);
		data.put("sign", s);
		String xmlStr = WXPayUtil.mapToXml(data);
		// 请求
		String response = doRefund(url, xmlStr).toString();
		// 处理请求结果
		Map<String, String> resultMap = new HashMap<String, String>();
		resultMap = wxPay.processResponseXml(response);
		// 解析返回值
		if ("SUCCESS".equals(resultMap.get("return_code").toString())
				&& "SUCCESS".equals(resultMap.get("result_code").toString())) {
			System.out.println("微信退单请求成功");
		} else {
			if (resultMap != null && "SUCCESS".equals(resultMap.get("return_code").toString())) {
				// 通信接口二级错误
				System.out.println("微信退单请求错误,通信接口二级错误：" + "result_code" + resultMap.get("result_code") + "err_code"
						+ resultMap.get("err_code") + "result_msg" + resultMap.get("err_code_des"));
			} else {
			}
		}
		// 验证结果是否成功
		return resultMap;

	}

	// 微信提现
	public static String transfers(String body, String totalFee, String partner_trade_no, String openId,
			HttpServletRequest request) throws Exception {
		Map<String, String> data = new HashMap();
		double amount = Double.valueOf(totalFee) * 100;
		String st = String.valueOf(amount);
		st = st.substring(0, st.indexOf("."));
		String url = WXPayConstants.TRANSFERS;
		OurWxPayConfig ourWxPayConfig = new OurWxPayConfig();
		WXPay wxPay = new WXPay(ourWxPayConfig);
		data.put("mch_appid", WeChatConfig.APP_ID);
		data.put("mchid", WeChatConfig.MCH_ID);
		data.put("nonce_str", WXPayUtil.generateNonceStr());
		data.put("partner_trade_no", partner_trade_no);
		data.put("openid", openId);
		data.put("check_name", "NO_CHECK");
		data.put("amount", st);
		data.put("desc", body);
		data.put("spbill_create_ip", WXPayUtil.getIpAddr(request));
		String s = WXPayUtil.generateSignature(data, WeChatConfig.APP_KEY);
		data.put("sign", s);
		String xmlStr = WXPayUtil.mapToXml(data);
		String response = doRefund(url, xmlStr).toString();
		// 处理请求结果
		Map<String, String> resultMap = new HashMap<String, String>();
		resultMap = XMLUtil.doXMLParse(response);
		return resultMap.get("result_code").toString();
	}

	public static String doRefund(String url, String data) throws Exception {
		KeyStore keyStore = KeyStore.getInstance("PKCS12");
		FileInputStream instream = new FileInputStream(new File(WeChatConfig.CERTIFICATE_URL));
		try {
			keyStore.load(instream, WeChatConfig.MCH_ID.toCharArray());
		} finally {
			instream.close();
		}
		SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, WeChatConfig.MCH_ID.toCharArray())
				.build();
		SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, new String[] { "TLSv1" }, null,
				SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
		CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
		try {
			HttpPost httpost = new HttpPost(url); // 设置响应头信息
			httpost.addHeader("Connection", "keep-alive");
			httpost.addHeader("Accept", "*/*");
			httpost.addHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
			httpost.addHeader("Host", "api.mch.weixin.qq.com");
			httpost.addHeader("X-Requested-With", "XMLHttpRequest");
			httpost.addHeader("Cache-Control", "max-age=0");
			httpost.addHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0) ");
			httpost.setEntity(new StringEntity(data.toString(), "UTF-8"));
			CloseableHttpResponse response = httpclient.execute(httpost);
			try {
				HttpEntity entity = response.getEntity();

				String jsonStr = EntityUtils.toString(response.getEntity(), "UTF-8");
				EntityUtils.consume(entity);
				System.out.println("jsonStr");
				return jsonStr;
			} finally {
				response.close();
			}
		} finally {
			httpclient.close();
		}
	}

	/**
	 * 支付结果查询
	 * 
	 * @throws Exception
	 */
	public static Map<String, String> queryPayStatus(String out_trade_no) throws Exception {
		// 把请求参数打包
		Map<String, String> params = new TreeMap<String, String>();
		params.put("appid", WeChatConfig.APP_ID);
		params.put("mch_id", WeChatConfig.MCH_ID);
		params.put("out_trade_no", out_trade_no);
		params.put("nonce_str", WXPayUtil.generateNonceStr());
		params.put("sign_type", WXPayConstants.MD5);
		params.put("sign", WXPayUtil.generateSignature(params, WeChatConfig.APP_KEY));
		// 把封装MAP转换成XML格式
		String queryXML = WXPayUtil.mapToXml(params);
		// 发起退款请求，并获取返回结果
		String resultXml = doRefund(WeChatConfig.ORDERQUERY_URL, queryXML).toString();
		if (StringUtils.isEmpty(resultXml)) {
			throw new Exception("请求错误，请检查参数是否合法，API能否正常访问");
		}
		System.out.println(resultXml);
		// 获取退款结果，转换成MAP集合
		Map<String, String> resultMap = WXPayUtil.xmlToMap(resultXml);
		// 验证结果是否成功
		return resultMap;

	}

}
